fix(llc): null ordering for pinned_at and last_message_at channel sorts - #2889
Conversation
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
9.27.0 is already tagged and published, so the entry belongs in a new Unreleased section rather than an existing released one. Matches the sibling v9 backport (#2889). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## v9 #2889 +/- ##
=====================================
Coverage ? 67.32%
=====================================
Files ? 431
Lines ? 27410
Branches ? 0
=====================================
Hits ? 18454
Misses ? 8956
Partials ? 0 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Submit a pull request
Linear: FLU-688
Github Issue: #
CLA
Description of the pull request
Backport of master commit
91ca8b63caa7398fb7e7209fde4e7b097317863b— "fix(llc): null ordering forpinned_atandlast_message_atchannel sorts" (#2878).SortOption's comparator placed NULLs using Postgres' default ordering (ASC → NULLS LAST,DESC → NULLS FIRST). The server doesn't use the default for every field — it applies explicitNULLS LASTtopinned_atandlast_message_at. SinceStreamChannelListController.valuere-sorts every response with this comparator, those two fields ended up ordered differently than the server returned them.Symptoms
[{pinned_at: -1}, {last_updated: -1}]— server returns pinned channels first; the SDK re-sorted them to the bottom.{last_message_at: -1}— server puts message-less channels last; the SDK floated every empty channel to the top.Ascending sorts were already correct, since the ascending default (
nullsLast) matches the server for both fields.Fix
nullOrderingis resolved from the field in each constructor's initializer list, so it stays aconstfield:pinned_at,last_message_at→nullsLastin both directionsnullOrderingstill winsPort notes
This was a manual port, not a clean cherry-pick — v9 formats at 80 cols (short style) vs master's tall/120, and v9's
SortOptionhas diverged from master's.Two changes go beyond the master commit, because without them the fix is inert on v9:
SortOption.fromJson— on v9 this was still the generated factory, which routes through the deprecated primary constructor and hardcodesnullsFirst, ignoring direction entirely. It is the only pathPredefinedFilter.sortand the offline persisted sort (ChannelStateSortOrderConverter) go through, so porting just the constructors would have left both broken. Master gained the hand-written factory in #2709; v9's backport of that feature (#2775) did not carry it over. Ported here, withcreateFactory: falseandsort_order.g.dartregenerated.SortOption()constructor — removed on master by an earlier cleanup, but still live public API on v9, so it kept the bug for anyone not yet migrated to.asc/.desc. Made field-aware too.API impact — source-compatible, patch-level:
nullOrderingwidens fromNullOrderingtoNullOrdering?on the parameter only; reads stay non-nullable and there are no subclasses ofSortOptionin the repo._$SortOptionFromJsonis library-private generated code, not public API;SortOption.fromJson's signature is unchanged.fromJsonkeeps the generated code's tolerantdirectionparse ((json['direction'] as num?)?.toInt() ?? SortOption.DESC) instead of master's hardas intcast, so payloads missingdirectionbehave exactly as before rather than throwing.Test instructions
Covers the field-aware defaults across both fields and directions, an explicit override beating a field-aware default,
fromJsonresolution (predefined filters), the missing-directionfallback, field-aware defaults on the deprecated constructor, and four ordering assertions over realChannelState: pinned-on-top in both directions, empty channels last forlast_message_at desc, and nulls-first preserved for a generic field so the general case can't silently regress.Results:
sort_order_test.dart28/28; fullstream_chatsuite 1311 passed / 2 skipped;stream_chat_persistence260 passed;stream_chat_flutter_core233 passed.dart analyze --fatal-infosandmelos run formatclean.Screenshots / Videos
No UI changes.